﻿namespace VisualSVN.Core.Licensing
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Security.Cryptography;

    public class RSAParametersLoader
    {
        public const string CSP_CONTAINER_NAME = "OSTY";

        private static RSAParameters DeserializeRSAKeyFromStream(Stream stream, string password)
        {
            RSAParameters parameters = new RSAParameters();
            using (stream)
            {
                BinaryFormatter formatter = new BinaryFormatter();
                parameters.Exponent = (byte[]) formatter.Deserialize(stream);
                parameters.Modulus = (byte[]) formatter.Deserialize(stream);
                if (password != null)
                {
                    long num = stream.Length - stream.Position;
                    byte[] buffer = new byte[num];
                    num = stream.Read(buffer, 0, (int) num);
                    PasswordDeriveBytes bytes = new PasswordDeriveBytes(password, null);
                    bytes.HashName = "SHA256";
                    Rijndael rijndael = new RijndaelManaged();
                    rijndael.KeySize = 0x100;
                    rijndael.Key = bytes.GetBytes(0x20);
                    rijndael.IV = new byte[rijndael.BlockSize / 8];
                    buffer = rijndael.CreateDecryptor().TransformFinalBlock(buffer, 0, (int) num);
                    rijndael.Clear();
                    MemoryStream serializationStream = new MemoryStream(buffer, false);
                    parameters.P = (byte[]) formatter.Deserialize(serializationStream);
                    parameters.Q = (byte[]) formatter.Deserialize(serializationStream);
                    parameters.D = (byte[]) formatter.Deserialize(serializationStream);
                    parameters.InverseQ = (byte[]) formatter.Deserialize(serializationStream);
                    parameters.DP = (byte[]) formatter.Deserialize(serializationStream);
                    parameters.DQ = (byte[]) formatter.Deserialize(serializationStream);
                    serializationStream.Close();
                }
                stream.Close();
                return parameters;
            }
        }

        public static RSAParameters LoadFromFile(string fileName, string password)
        {
            Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            return DeserializeRSAKeyFromStream(stream, password);
        }

        public static RSAParameters LoadFromResource(Assembly assembly, string resourceName, string password)
        {
            string name = assembly.GetName().Name;
            return DeserializeRSAKeyFromStream(assembly.GetManifestResourceStream(name + "." + resourceName), password);
        }
    }
}

